package com.eden.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.eden.config.Configuration;
import com.eden.config.Score;
import com.eden.config.ScoreRange;
import com.eden.constant.Constant;
import com.eden.entity.AnalyzeResult;
import com.eden.entity.ScoreDistribution;
import com.eden.service.AnalyzeService;
import com.eden.ui.Model;
import com.eden.util.NumberFormatUtil;
import com.eden.util.TypeConvertUtil;

public class AnalyzeServiceImpl extends BaseServiceImpl implements AnalyzeService {

	private final static Log log = LogFactory.getLog(AnalyzeServiceImpl.class) ;
	
	public Model analize(List<Map<String, Object>> scoreList , Configuration configuration) {
		try {
			List<Score> scoreDist = configuration.getScoreList() ;
			int total = configuration.getTotal() ;
//		分数分布情况
			Map<String , Double> scoreDistMap = new HashMap<String, Double>() ;
			for(Score score : scoreDist) {
				if(score.isValid()) {
					scoreDistMap.put(score.getName(), score.getPercent()) ;
				}
			}
			
//		计算总成绩
			log.info("compute total score...") ;
			List<Double> totalScoreList = new ArrayList<Double>() ;
//		从1开始,第0行为表头
			for(int i = 1 , length = scoreList.size() ; i < length ; i++) {
				Map<String, Object> m = scoreList.get(i) ;
				double sum = 0 ;
				for(Entry<String, Double> entry : scoreDistMap.entrySet() ) {
					sum += TypeConvertUtil.toDouble(m.get(entry.getKey())) * entry.getValue() ;
				}
				sum = NumberFormatUtil.formatDouble(sum, Constant.TOTAL_SCORE_SCALE) ;
				m.put(Constant.TOTAL_SCORE, sum) ;
				totalScoreList.add(sum) ;
			}
			log.info("total score :" + totalScoreList ) ;
			
			AnalyzeResult ar = new AnalyzeResult() ;
			//最高分
			ar.setMaxScore(Collections.max(totalScoreList)) ;
			//最低分
			ar.setMinScore(Collections.min(totalScoreList)) ;
			//平均分
			ar.setAverage(getAverage(totalScoreList)) ;
			//区分度
			ar.setDifferentiation(getDifferentiation(totalScoreList , total)) ;
			//难度
			ar.setDifficulty(getDifficulty(totalScoreList , ar.getAverage())) ;
			//优良率
			ar.setGoodRate(getGoodRate(totalScoreList , total)) ;
			//通过率
			ar.setPassRate(getPassRate(totalScoreList , total)) ;
			ar.setVariance(getVariance(totalScoreList , ar.getAverage())) ;
			ar.setStandardDeviation(getStandardDeviation(ar.getVariance())) ;
			
			ar.setEvaluation(getEvaluation(ar)) ;
			log.info("analyze score result : " + ar) ;
			
//			计算每个分数段的人数 
			Map<String,List<Double>> scoreToAnalyzeMap = new HashMap<String, List<Double>>() ;
			for(Score score : scoreDist) {
				//如果此科成绩需要分析,加入将要分析的Map中
				if(score.isAnalyze()) {
					String scoreName = score.getName() ;
					List<Double> scoreList2 = new ArrayList<Double>() ;
					for(int i = 1 , length = scoreList.size() ; i < length ; i++) {
						scoreList2.add(TypeConvertUtil.toDouble(scoreList.get(i).get(scoreName))) ;
					}
					scoreToAnalyzeMap.put(scoreName, scoreList2) ;
				}
			}
			scoreToAnalyzeMap.put(Constant.TOTAL_SCORE, totalScoreList) ;
			
			ScoreDistribution sd = new ScoreDistribution() ;
			List<String> columnKeyList = new ArrayList<String>() ;
			//取得分数分布区间的配置
			List<ScoreRange> scoreRangeList = configuration.getScoreRangeList() ;
			for(ScoreRange scoreRange : scoreRangeList){
				columnKeyList.add(scoreRange.getName()) ;
			}
			sd.setColumnKeys(columnKeyList.toArray(new String[20])) ;
			
			//{"zongchengji":{'30-40' : 20}} 格式
			Map<String , Map<String , Double>> scoreDistributeMap = new HashMap<String, Map<String,Double>>() ;
			//对需要图表显示的成绩进行人数分布统计
			for(Entry<String , List<Double>> entry : scoreToAnalyzeMap.entrySet()) {
				Map<String , Double> item = new HashMap<String, Double>() ;
				for(Double score : entry.getValue()){
					for(ScoreRange scoreRange : scoreRangeList){
						Double curr = item.get(scoreRange.getName()) ;
						curr = curr==null?0 :curr ;
						if(scoreRange.getMin() == -1 ){
							if(score < scoreRange.getMax()){
								item.put(scoreRange.getName(), ++curr) ;
								break ;
							}
						} else {
							if(scoreRange.getMax() == -1) {
								if(score >= scoreRange.getMin()){
									item.put(scoreRange.getName(), ++curr) ;
									break ;
								}
							} else {
								if(score < scoreRange.getMax() && score >= scoreRange.getMin()){
									item.put(scoreRange.getName(), ++curr) ;
									break ;
								}
							}
						}
					}
				}
				scoreDistributeMap.put(entry.getKey(), item) ;
			}
			log.info("score distribute :" + scoreDistributeMap) ;
			
			
			Model model = new Model() ;
			model.setAttribute(Constant.ANALYZE_RESULT_KEY, ar) ;
			model.setAttribute(Constant.TOTAL_SCORE_LIST_KEY, totalScoreList) ;
			model.setAttribute(Constant.SCORE_LIST_KEY, scoreList) ;
			model.setAttribute(Constant.SCORE_DISTRIBUTE_KEY, scoreDistributeMap) ;
			return model;
		} catch (Exception e) {
			log.error("analyze score error : " , e) ;
		}
		return null;
	}

	
	public double getAverage(List<Double> totalScoreList) {
		if(totalScoreList.size() == 0)
			return 0;
		double sum = 0;
		for(int i = 0 ;i<totalScoreList.size() ;i++){
			sum = sum + totalScoreList.get(i);
		}
		return NumberFormatUtil.formatDouble(sum/totalScoreList.size() , Constant.TOTAL_SCORE_SCALE);
	}
	
//	返回难度系数
	public double getDifficulty(List<Double> totalScoreList , double average) {
		return NumberFormatUtil.formatDouble(1-average/100 , Constant.TOTAL_SCORE_SCALE);
	}

//	返回标准差
	public double getStandardDeviation(double variance) {
		return NumberFormatUtil.formatDouble(Math.sqrt(variance) , Constant.TOTAL_SCORE_SCALE);
	}

//	返回方差
	public double getVariance(List<Double> totalScoreList , double average) {
		double sum = 0;
		for(int i = 0 ;i<totalScoreList.size() ;i++){
			sum = sum + Math.pow((average - totalScoreList.get(i)), 2);
		}
		return NumberFormatUtil.formatDouble(sum/totalScoreList.size() , Constant.TOTAL_SCORE_SCALE);
		
	}

//	返回通过率
	public double getPassRate(List<Double> totalScoreList , int total) {
		double count = 0;
		for(int i = 0 ;i < totalScoreList.size() ;i++){
			if(totalScoreList.get(i) > total * 0.6){
				count++;
			}
		}
		return NumberFormatUtil.formatDouble(count / totalScoreList.size() , Constant.TOTAL_SCORE_SCALE);
	}

//	返回优良率
	public double getGoodRate(List<Double> totalScoreList , int total) {
		double count = 0;
		for(int i = 0 ;i < totalScoreList.size() ;i++){
			if(totalScoreList.get(i) > total * 0.70){
				count++;
			}
		}
		return NumberFormatUtil.formatDouble(count / totalScoreList.size() , Constant.TOTAL_SCORE_SCALE);
	}

//	返回区分度
	public double getDifferentiation(List<Double> totalScoreList , int total) {
		double highScore = 0;
		double lowScore = 0;
		if(totalScoreList.size() % 2 == 0){
			for(int i = 0 ;i < totalScoreList.size() / 2  ;i++){
				lowScore += totalScoreList.get(i);
				highScore += totalScoreList.get(totalScoreList.size() -1 -i);
			}
		} 
		else {
			for(int i = 0 ;i < totalScoreList.size() / 2  ;i++){
				lowScore += totalScoreList.get(i);
				highScore += totalScoreList.get(totalScoreList.size() - 1 -i);
			}
		}
		
		double differentiation = (highScore * 0.27 - lowScore * 0.27) / total  ;
		return NumberFormatUtil.formatDouble( differentiation , Constant.TOTAL_SCORE_SCALE);
	}

//	返回正态性
	public String getDistribution(){
		
		return "";
	}
	
	//返回机器评测
	public String getEvaluation(AnalyzeResult ar){
		String evaluation = "依据教育测量学理论，检测发现：" ;
		if(ar.getDifficulty()<0.3){
			evaluation += "考试试题难度整体似乎偏容易，" ;
		}
		if(ar.getDifficulty()<0.7&&ar.getDifficulty()>0.3){
			evaluation += "考试试题难度整体适中，" ;
		}
		if(ar.getDifficulty() > 0.7){
			evaluation += "考试试题难度整体偏难，" ;
		}
		
		//区分度
		if(ar.getDifferentiation()>=0.4){
			evaluation +="考试区分度为优级," ;
		}

		if(ar.getDifferentiation()<0.4 && ar.getDifferentiation()>=0.3){
			evaluation +="考试区分度良好," ;
		}
		if(ar.getDifferentiation()<0.3 && ar.getDifferentiation()>=0.2){
			evaluation +="考试区分度一般,需要注意提高考试区分性能" ;
		}
		if(ar.getDifferentiation()<0.2){
			evaluation +="考试区分度差,需要注意提高考试区分性能" ;
		}
		
		
		return evaluation ;
	}
}
